package com.ply.service.impl;

import com.ply.entity.pojo.DetailAccountRecord;
import com.ply.entity.pojo.Project;
import com.ply.entity.pojo.User;
import com.ply.entity.pojo.VoteOption;
import com.ply.entity.vo.ConsumerMsg;
import com.ply.entity.vo.ProjectAndOption;
import com.ply.entity.vo.ProjectOption;
import com.ply.entity.vo.Result;
import com.ply.mapper.UserMapper;
import com.ply.service.LevelService;
import com.ply.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author XiaoPan
 * date: 2022/1/4 21:37
 * <p>
 * action:
 * <p>
 * 登录
 * 注册
 * 充值
 * 升级
 * 发起投票
 * 购买次数
 * 购买天数
 * 提现
 * <p>
 * 增加次数
 * 余额的增加
 * 总金额增加
 * 等级提升
 * <p>
 * <p>
 * 更新user表(注册,***)
 * 更新detail_account_record表 (消费时增加记录,充值时)
 * <p>
 * 公有方法:
 * 查看我的消费记录
 * <p>
 * 查询投票结果 (参数: 项目id , 返回 每个选项的信息,票数,List<VoteOption>);
 * 查询我的所有创建投票(参数 用户id  返回每个项目的信息, List<Project></>)
 * 可以在 后面 做一个方法 调用 begin  和 end
 */

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    private final LevelService levelService;
    private final ProjectServiceImpl projectService;
    private final AccountRecordServiceImpl accountRecord;
    private final UserMapper userMapper;

    public UserServiceImpl(LevelService levelService, ProjectServiceImpl projectService, AccountRecordServiceImpl accountRecord, UserMapper userMapper) {
        this.levelService = levelService;
        this.projectService = projectService;
        this.accountRecord = accountRecord;
        this.userMapper = userMapper;
    }

    /**
     * 登录
     *
     * @param name 用户名
     * @param pwd  密码
     * @return 成功与否
     */
    public Result<?> login(String name, String pwd) {

        User user = userMapper.queryUserByName(name);
        if (user == null) {
            return Result.fail("用户名不存在");
        }
        if (!(user.getPasswd().equals(pwd))) {
            return Result.fail("密码错误");
        }
//        返回数据中将密码更换
        user.setPasswd("00");
        //将用户存进Map中方便获取Map中的

        return Result.ok("用户名密码正确", user);

        //修改代码   Mysql
    }

    /**
     * 注册
     *
     * @param user 用户实体类
     * @return 成功与否
     */

    public Result<?> register(User user) {
        //todo 注册用户名 密码检测 用户名 需要 3-15字符  密码 6-20 需要过滤 特殊字符
        if (Objects.equals(user.getName(), "") || user.getName() == null || Objects.equals(user.getPasswd(), "") || user.getPasswd() == null) {
            return Result.fail("用户名或密码为空");
        }

        //todo 注册不需要审核
//        manageService.registerCheck(user);
        User user1 = userMapper.queryUserByName(user.getName());
        if (user1 != null) {
            return Result.fail("账户名重复");
        }
        if (userMapper.addUser(user) == 0) return Result.fail("数据库插入失败");
        return Result.ok("注册成功");
    }


    /**
     * 发起投票  发起投票 ()  查询剩余投票次数   增加时间 需充值 可以指定一个投票人 一天投n票
     *
     * @return 发起投票成功与否  还会有审核的
     */

    @Transactional
    public Result<?> sendVote(ProjectAndOption projectAndOption) {
//      查询剩余投票次数 从数据库中查找用户信息 中有 剩余投票数
        User user = userMapper.queryUserByUserId(projectAndOption.getProject().getUserId());

        Integer remainVoteSum = user.getRemainVoteSum();
        if (remainVoteSum > 0) {
            // 发送给 项目业务
            //如果在projectService 中返回 fail 就直接return
            Result<?> createVoteResult = projectService.createVote(projectAndOption);
            log.info("在 userService 中的 sendVote createVoteResult {}", createVoteResult);

            if (!createVoteResult.isTrue()) {
                return createVoteResult;
            }
            // 剩余投票次数-1;
            return decSendVote(projectAndOption.getProject().getUserId(), remainVoteSum);

        }
        return Result.fail("剩余投票次数不够");
    }

    @Transactional
    public Result<?> sendVote(Project project) {
//      查询剩余投票次数 从数据库中查找用户信息 中有 剩余投票数
        User user = userMapper.queryUserByUserId(project.getUserId());

        Integer remainVoteSum = user.getRemainVoteSum();
        if (remainVoteSum > 0) {
            // 发送给 项目业务
            //如果在projectService 中返回 fail 就直接return
            Result<?> createVoteResult = projectService.createVote(project);
            log.info("在 userService 中的 sendVote createVoteResult {}", createVoteResult);

            if (!createVoteResult.isTrue()) {
                return createVoteResult;
            }
            // 剩余投票次数-1;
            return decSendVote(user.getId(), remainVoteSum);

        }
        return Result.fail("剩余投票次数不够");
    }

    //增加 选项list
    @Transactional
    public Result<?> addVoteOptionList(Integer projectId, List<VoteOption> voteOptionList) {
        return projectService.addVoteOptionList(projectId,voteOptionList);

    }

    @Transactional
    public Result<?> addVoteOption(Integer projectId, VoteOption voteOption) {
        return projectService.addVoteOption(projectId,voteOption);
    }

//    充值

    /**
     * 会员充值
     *
     * @param userId 用户id
     *               //     * @param levelId 等级id
     * @param amount 充值的金额
     * @return 是否成功
     */
    // 加入事务
    @Transactional
    public Result<?> recharge(int userId, double amount) {
        //通过userId 查询 levelId
        User user = userMapper.queryUserByUserId(userId);

        if (user == null) {
            return Result.fail("数据库错误   通过userId 查询 user 错误");
        }

        // 余额增加
        addRemainMoney(userId, user.getRemainSum() + amount);
        //需要判断是否成功
        //总金额增加
        addAccount(userId, user.getChargeTotalAmount() + amount);
        //升级 方法
        up(userId, user.getLevelId());

        //增加流水记录
        return accountRecord.addAccountRecord(userId, amount);
    }

    /**
     * 消费方法
     *
     * @param userId         用户id
     * @param amount         金额
     * @param consumerMsg    消费类型
     * @param dayOrVoteCount 天数或者是发起投票次数
     */
    @Transactional
    public Result<?> shopping(int userId, double amount, ConsumerMsg consumerMsg, int dayOrVoteCount, Integer projectId) {
        //调用 账户的 流水
//      查询用户余额  看看 用户余额 够不够
        User user = userMapper.queryUserByUserId(userId);

//        Integer remainVoteSum = user.getRemainVoteSum();


        Double remainSum = user.getRemainSum();

        if (remainSum < amount) {
            return Result.fail("购买失败: 你的余额是:" + remainSum + "\t 但是你想购买的次数" + dayOrVoteCount + "的价格为:" + amount + "所以你要充值");
        }

        return consumption(userId, amount, consumerMsg, dayOrVoteCount, projectId);
    }


    /**
     * 增加总金额
     *
     * @param userId 用户id
     * @param amount 增加的总金额
     */
    public Result<?> addAccount(int userId, double amount) {
        // 告诉用户 自己将 总金额增加
        return addChargeTotalAmount(userId, amount);
    }


    /**
     * 用户余额变化 充值会调用 消费会调用
     *
     * @param userId    用户id
     * @param newAmount 新的余额
     * @return 成功失败
     */
    //更新 user表中
    public  Result<?> addRemainMoney(int userId, double newAmount) {
        //插入到数据库的
        userMapper.updateUserRemainSum(userId, newAmount);
        return Result.ok();
    }


    /**
     * 增加用户充值的总金额
     *
     * @param userId    用户id
     * @param newAmount 用户增加的金额
     */

    public Result<?> addChargeTotalAmount(int userId, double newAmount) {
        //插入到数据库的
        userMapper.updateUserCharge(userId, newAmount);
        return Result.ok();
    }


    /**
     * 说明 : 将剩余投票数 增加
     *
     * @param userId 用户id
     * @return 成功与否
     */
    public  Result<?> addRemainVote(int userId, int sum) {
        //写入到数据库 user表中   remain_vote_sum+1
        userMapper.updateUserRemainVoteSum(userId, sum);
        return Result.ok();
    }

    /**
     * 说明 : 将剩余投票数 减一
     *
     * @param userId 用户id
     * @return 成功与否
     */

    public  Result<?> decSendVote(int userId, int remainVoteSum) {
        //写入到数据库 user表中   remain_vote_sum -1
        userMapper.updateUserRemainVoteSum(userId, remainVoteSum - 1);
        return Result.ok();
    }


//   升级

    /**
     * 判断用户是否可以升级
     *
     * @param levelId 等级id
     * @return 返回成功是否
     */
    public  Result<?> up(int userId, int levelId) {
        //查询 等级id

//        根据等级id 叫 等级对象 查询升下一级的 总金额
        User user = userMapper.queryUserByUserId(userId);

        Double chargeTotalAmount = user.getChargeTotalAmount();

        Result<?> toUp = levelService.isToUp(levelId, chargeTotalAmount);

        Map<String, Integer> date = (Map<String, Integer>) toUp.getDate();

//        System.out.println("toUp"+ toUp);

        if (toUp.isTrue()) {

            //更新 用户等级
            userMapper.updateUserLevelId(userId, date.get("levelId"));

//        可以升级的话 返回 下一等级 的发送次数
//            int i = levelService.selectSendVoteSum(levelId + 1);

            //查询 原有的 发送次数
            Integer remainVoteSum = userMapper.queryUserByUserId(userId).getRemainVoteSum();

            //更新user 表中的 send_vote_num   增加数 在 等级表中查询
            addRemainVote(userId, remainVoteSum + date.get("num"));

            return Result.ok("升级成功");
        }
        return Result.fail("总金额不够升级");

    }


    /**
     * 消费记录
     *
     * @param userId 用户id
     * @param amount 金额
     * @param msg    用途
     */
    public  Result<?> consumption(int userId, double amount, ConsumerMsg msg, int dayOrVoteCount, Integer projectId) {
        // 写入数据库 流水
        if (msg.getId() == 0) {
            //说明  用于购买发起投票次数

            User user = userMapper.queryUserByUserId(userId);

            Integer remainVoteSum = user.getRemainVoteSum();


            Result<?> result = addRemainVote(userId, dayOrVoteCount + remainVoteSum);

            if (!result.isTrue()) {
                return result;
            }

        } else if (msg.getId() == 1) {

            Result<?> result = projectService.byProjectEndTime(1,projectId, dayOrVoteCount);

            if (!result.isTrue()) {
                return result;
            }
            //说明  用于购买投票延长时间


//            投票延长时间 +1   是Project 对象 的方法
//            addVoteDay(userId);
        }
        //怎么样都要 增加到流水表中  因为是消费 所以是负的
        accountRecord.addAccountRecord(userId, -amount);

        User user = userMapper.queryUserByUserId(userId);

        Double remainSum = user.getRemainSum();
        //用户 余额变化  + amount
        addRemainMoney(userId, remainSum-amount);
        return Result.ok();

    }

    /**
     * 查询等级 通过用户 id
     *
     * @param userId 用户id
     * @return 用户等级
     */
    public int queryLevelByUserId(int userId) {
        User user = userMapper.queryUserByUserId(userId);
        return user.getLevelId();
    }



    /**
     * 查询所有用户  分页   参数 : 当前页码  每页条数
     *
     * @param pageIndex 当前页数
     * @param pageSum:  每页条数
     * @return 返回值中会有 所有用户
     */
    public Result<?> queryUserAll(Integer pageIndex, Integer pageSum) {
        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;
        List<User> users = userMapper.queryUserAll(begin, end);
        for (User user : users) {
            user.setPasswd("###");
        }
        return Result.ok(users);
    }

    /**
     * 不分页
     *
     */
    public Result<?> queryUserAll() {
        Integer begin = null;
        Integer end = null;
        List<User> users = userMapper.queryUserAll(begin, end);
        for (User user : users) {
            user.setPasswd("###");
        }
        return Result.ok(users);
    }

    /**
     * 通过 用户id 查询 流水记录
     */
    public Result<?> queryAllByUserId(Integer pageIndex, Integer pageSum, Integer userId) {
        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;

        List<DetailAccountRecord> detailAccountRecords = userMapper.queryAllByUserId(begin, end, userId);

        return Result.ok("查询自己的流水记录", detailAccountRecords);

    }

    /**
     * 通过 用户id 查询 流水记录 (不分页)
     *
     */
    public Result<?> queryAllByUserId(Integer userId) {
        Integer begin = null;
        Integer end = null;

        List<DetailAccountRecord> detailAccountRecords = userMapper.queryAllByUserId(begin, end, userId);

        return Result.ok("查询自己的流水记录", detailAccountRecords);
    }

    /**
     * 查询 所有用户的流水 (分页)
     */
    public Result<?> queryAllByUserRecode(Integer pageIndex, Integer pageSum) {

        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;

        List<DetailAccountRecord> detailAccountRecords = userMapper.queryAllByUserRecode(begin, end);

        return Result.ok("查询到所有用户的流水记录 分页", detailAccountRecords);

    }

    /**
     * 查询 所有用户的流水 (分页)
     */
    public Result<?> queryAllByUserRecode() {

        Integer begin = null;
        Integer end = null;

        List<DetailAccountRecord> detailAccountRecords = userMapper.queryAllByUserRecode(begin, end);

        return Result.ok("查询到所有用户的流水记录 分页", detailAccountRecords);
    }

    /**
     * 查询 所有 的 项目  选项
     */

    public Result<?> queryAllProject(Integer pageIndex, Integer pageSum) {
        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;

        List<ProjectOption> projectOptions = userMapper.queryAllProject(begin, end);

        return Result.ok("查询 所有 的 项目  选项 分页", projectOptions);
    }

    /**
     * 查询 所有 的 项目  选项 (不分页)
     */

    public Result<ProjectOption> queryAllProject() {
        Integer begin = null;
        Integer end = null;

        List<ProjectOption> projectOptions = userMapper.queryAllProject(begin, end);

        return Result.ok("查询 所有 的 项目  选项 分页", projectOptions);
    }

    /**
     * 查询 用户的所有 创建的  选项
     */

    public Result<?> queryMyProject(Integer pageIndex, Integer pageSum, Integer userId) {
        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;

        log.info("queryMyProject begin:{}, end:{}",begin,end);

        List<ProjectOption> projectOptions = userMapper.queryMyProject(begin, end, userId);

        return Result.ok("查询我的创建投票", projectOptions);
    }

    /**
     * 查询 用户的所有 创建的  选项
     */

    public Result<?> queryMyProject(Integer userId) {
        Integer begin = null;
        Integer end = null;
        List<ProjectOption> projectOptions = userMapper.queryMyProject(begin, end, userId);
        return Result.ok("查询我的创建投票", projectOptions);
    }






    /**
     * 查询 用户的所有 创建的  选项
     */

    public Result<?> queryMyProjectNoVoteOp(Integer pageIndex, Integer pageSum, Integer userId) {
        Integer begin = (pageIndex - 1) * pageSum;
        Integer end = (pageIndex) * pageSum;

        log.info("queryMyProject begin:{}, end:{}",begin,end);

        List<Project> project = userMapper.queryMyProjectNoVoteOp(begin, end, userId);

        return Result.ok("查询我的创建投票", project);
    }


}
